#include <iostream>
#include <memory>
#include <new>

// ==================== 演示类 ====================
class ResourceHolder {
private:
    int* data;
    std::string name;
    
public:
    ResourceHolder(const std::string& n) : name(n) {
        data = new int[5]{1, 2, 3, 4, 5};
        std::cout << "构造 " << name << " (分配了资源)" << std::endl;
    }
    
    ~ResourceHolder() {
        delete[] data;
        std::cout << "析构 " << name << " (释放了资源) *** 重要的副作用 ***" << std::endl;
    }
    
    void show() const {
        std::cout << name << " 的数据: ";
        for (int i = 0; i < 5; i++) {
            std::cout << data[i] << " ";
        }
        std::cout << std::endl;
    }
    
    // 禁用拷贝以简化示例
    ResourceHolder(const ResourceHolder&) = delete;
    ResourceHolder& operator=(const ResourceHolder&) = delete;
};

// ==================== 1. 正常情况：析构函数自动调用 ====================
void test_normal_destruction() {
    std::cout << "\n=== 1. 正常析构（栈对象） ===" << std::endl;
    
    {
        ResourceHolder obj("栈对象");
        obj.show();
    } // 作用域结束，析构函数自动调用
    
    std::cout << "栈对象已销毁" << std::endl;
}

void test_dynamic_allocation() {
    std::cout << "\n=== 2. 动态分配（使用delete） ===" << std::endl;
    
    ResourceHolder* ptr = new ResourceHolder("堆对象");
    ptr->show();
    
    delete ptr; // 显式调用delete，析构函数被调用
    std::cout << "堆对象已销毁" << std::endl;
}

// ==================== 3. 重用存储空间（Placement New） ====================
void test_storage_reuse() {
    std::cout << "\n=== 3. 重用存储空间（Placement New） ===" << std::endl;
    
    // 分配原始内存
    alignas(ResourceHolder) char buffer[sizeof(ResourceHolder)];
    
    // 在buffer中构造第一个对象
    ResourceHolder* obj1 = new(buffer) ResourceHolder("Placement对象1");
    obj1->show();
    
    // 显式调用析构函数（必须的！）
    obj1->~ResourceHolder();
    std::cout << "手动调用了析构函数" << std::endl;
    
    // 重用同一块内存构造第二个对象
    ResourceHolder* obj2 = new(buffer) ResourceHolder("Placement对象2");
    obj2->show();
    
    // 再次显式调用析构函数
    obj2->~ResourceHolder();
    std::cout << "再次手动调用了析构函数" << std::endl;
    
    // 注意：不需要delete，因为buffer是栈分配的
}

// ==================== 4. 危险情况：不调用析构函数 ====================
void test_dangerous_no_destructor() {
    std::cout << "\n=== 4. 危险：不调用析构函数 ===" << std::endl;
    
    alignas(ResourceHolder) char buffer[sizeof(ResourceHolder)];
    
    // 构造对象
    ResourceHolder* obj = new(buffer) ResourceHolder("危险对象");
    obj->show();
    
    // 危险：直接重用存储空间，不调用析构函数
    std::cout << "警告：即将重用存储空间而不调用析构函数..." << std::endl;
    
    // 这里应该调用 obj->~ResourceHolder() 但我们故意不调用
    // obj->~ResourceHolder(); // 应该调用但故意注释掉
    
    // 直接在同一块内存构造新对象
    ResourceHolder* obj2 = new(buffer) ResourceHolder("新对象");
    obj2->show();
    
    std::cout << "注意：原对象的析构函数从未被调用！" << std::endl;
    std::cout << "这导致了内存泄漏和未定义行为！" << std::endl;
    
    // 清理新对象（至少这个要清理）
    obj2->~ResourceHolder();
}

// ==================== 5. malloc/free 的情况 ====================
void test_malloc_free() {
    std::cout << "\n=== 5. malloc/free：析构函数不会自动调用 ===" << std::endl;
    
    // 使用malloc分配内存
    void* raw_memory = std::malloc(sizeof(ResourceHolder));
    if (!raw_memory) {
        std::cout << "内存分配失败" << std::endl;
        return;
    }
    
    // 使用placement new构造对象
    ResourceHolder* obj = new(raw_memory) ResourceHolder("malloc对象");
    obj->show();
    
    // 重要：必须显式调用析构函数
    obj->~ResourceHolder();
    std::cout << "显式调用了析构函数" << std::endl;
    
    // 使用free释放内存（不会调用析构函数）
    std::free(raw_memory);
    std::cout << "使用free释放了内存" << std::endl;
}

// ==================== 6. 错误示例：依赖析构函数副作用 ====================
void test_undefined_behavior() {
    std::cout << "\n=== 6. 未定义行为：依赖析构函数副作用 ===" << std::endl;
    
    void* raw_memory = std::malloc(sizeof(ResourceHolder));
    ResourceHolder* obj = new(raw_memory) ResourceHolder("副作用对象");
    
    // 程序依赖析构函数的副作用（资源清理）
    // 但直接使用free，不调用析构函数
    std::cout << "错误：直接free而不调用析构函数..." << std::endl;
    
    std::free(raw_memory); // 错误：没有调用析构函数
    
    std::cout << "结果：内存泄漏！析构函数的清理工作未执行！" << std::endl;
    std::cout << "这就是标准中提到的'未定义行为'" << std::endl;
}

// ==================== 7. 正确的资源管理 ====================
void test_correct_resource_management() {
    std::cout << "\n=== 7. 正确的资源管理方式 ===" << std::endl;
    
    // 方式1：使用智能指针
    {
        std::unique_ptr<ResourceHolder> smart_ptr(new ResourceHolder("智能指针对象"));
        smart_ptr->show();
    } // 智能指针自动调用delete，析构函数被正确调用
    
    // 方式2：RAII包装器
    class RAIIWrapper {
    private:
        void* memory;
        ResourceHolder* obj;
        
    public:
        RAIIWrapper(const std::string& name) {
            memory = std::malloc(sizeof(ResourceHolder));
            obj = new(memory) ResourceHolder(name);
        }
        
        ~RAIIWrapper() {
            if (obj) {
                obj->~ResourceHolder(); // 显式调用析构函数
                std::free(memory);      // 释放内存
            }
        }
        
        ResourceHolder* get() { return obj; }
    };
    
    {
        RAIIWrapper wrapper("RAII对象");
        wrapper.get()->show();
    } // RAII确保正确的清理顺序
}

int main() {
    std::cout << "=== C++对象生命周期和析构函数调用规则演示 ===" << std::endl;
    
    test_normal_destruction();
    test_dynamic_allocation();
    test_storage_reuse();
    test_dangerous_no_destructor();
    test_malloc_free();
    test_undefined_behavior();
    test_correct_resource_management();
    
    std::cout << "\n=== 总结 ===" << std::endl;
    std::cout << "1. 栈对象和new/delete：析构函数自动调用" << std::endl;
    std::cout << "2. placement new：必须手动调用析构函数" << std::endl;
    std::cout << "3. malloc/free：必须手动调用析构函数" << std::endl;
    std::cout << "4. 不调用析构函数：导致资源泄漏和未定义行为" << std::endl;
    
    return 0;
}
